home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK1.toast / Development Kits / Mac OS / Navigation Services SDK / Examples / Sampler / Sampler ƒ / file.c < prev    next >
Encoding:
Text File  |  1999-06-16  |  23.4 KB  |  903 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        file.c
  3.  
  4.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  5.  
  6. */
  7.  
  8. //    
  9. //    You may incorporate this sample code into your applications
  10. //    without restriction. This sample code has been provided "AS
  11. //    IS" and the responsibility for its operation is 100% yours.
  12. //    You are not permitted to redistribute the source as "Apple
  13. //    sample code" after having made changes. If you're going to
  14. //    re-distribute the source, we require that you make it clear
  15. //    in the source that the code was descended from Apple sample
  16. //    code, but that you've made changes.
  17. //    
  18.  
  19. #pragma segment DocSeg
  20.  
  21. #ifndef __STRINGS__
  22. #include <Strings.h>
  23. #endif
  24.  
  25. #ifndef __STDIO__
  26. #include <StdIO.h>
  27. #endif
  28.  
  29. #ifndef __STANDARDFILE__
  30. #include <StandardFile.h>
  31. #endif
  32.  
  33. #ifndef __FINDER__
  34. #include <Finder.h>
  35. #endif
  36.  
  37. #ifndef __SOUND__
  38. #include <Sound.h>
  39. #endif
  40.  
  41. #ifndef __NAVIGATION__
  42. #include "Navigation.h"
  43. #endif
  44.  
  45.  
  46. #ifndef Common_Defs
  47. #include "Common.h"
  48. #endif
  49.  
  50. const long kPictHeaderSize = 512;
  51.  
  52. extern short gDocumentCount;
  53.  
  54. short ReadFile(Document* theDocument);
  55. short WriteFile(Document* theDocument);
  56. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec);
  57. short DoSaveAsDocument(Document* theDocument);
  58. short DoSaveAsDocumentOldWay(Document* theDocument);
  59.  
  60. pascal Boolean myFilterProc(AEDesc* theItem, void* info, NavCallBackUserData callBackUD, NavFilterModes filterMode);
  61.  
  62. extern Document* gDocumentList[kMaxDocumentCount];
  63. extern Boolean gNavServicesExists;
  64.  
  65.  
  66. // *****************************************************************************
  67. // *
  68. // *    ReadFile()
  69. // *
  70. // *****************************************************************************
  71. short ReadFile(Document* theDocument)
  72. {    
  73.     long        count;
  74.     short        theResult;
  75.     char        buffer[256];
  76.     TextStyle    theStyle;
  77.  
  78.     SetCursor(*GetCursor(watchCursor));
  79.  
  80.     if (theDocument->theTE != NULL)
  81.         {
  82.         TESetSelect(0,(**(theDocument->theTE)).teLength,theDocument->theTE);
  83.         TEDelete(theDocument->theTE);
  84.  
  85.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  86.             return theResult;
  87.  
  88.         do    {
  89.             count = 256;
  90.             theResult = FSRead(theDocument->fRefNum,&count,&buffer);
  91.             TEInsert(&buffer,count,theDocument->theTE);
  92.             }
  93.         while (theResult == noErr);
  94.  
  95.         if (theResult == eofErr)
  96.             theResult = noErr;
  97.     
  98.         TESetSelect(0,32767,theDocument->theTE);
  99.         theStyle.tsFont = 21;
  100.         theStyle.tsSize = 12;
  101.         TESetStyle(doFont + doSize,&theStyle,true,theDocument->theTE);
  102.         TESetSelect(0,0,theDocument->theTE);
  103.         }
  104.     else
  105.         {
  106.         short     result = noErr;
  107.         long    fileSize = 0;
  108.         long    headerSize = 0;
  109.         long    pictSize = 0;
  110.  
  111.         SetCursor(*(Cursor**)GetCursor(watchCursor));
  112.         
  113.         if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  114.             return theResult;
  115.  
  116.         theResult = GetEOF(theDocument->fRefNum,&fileSize);
  117.         
  118.         theDocument->fPictLength = fileSize;
  119.         theDocument->fPictLength -= kPictHeaderSize;
  120.         theDocument->fPict = NewHandle(theDocument->fPictLength);
  121.         theDocument->fHeader = NewHandle(kPictHeaderSize);
  122.         if ((theDocument->fPict == NULL)||(theDocument->fPict == NULL))
  123.             return memFullErr;
  124.             
  125.         headerSize = kPictHeaderSize;
  126.         pictSize = theDocument->fPictLength;
  127.  
  128.         theResult = FSRead(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  129.         theResult = FSRead(theDocument->fRefNum,&pictSize,*theDocument->fPict);
  130.         }
  131.  
  132.     theDocument->dirty = false;
  133.  
  134.     if (theResult != noErr)
  135.         {
  136.         Str255 errorStr;
  137.         GetIndString(errorStr,rAppStringsID,sReadErr);
  138.         ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  139.         NoteAlert(rGenericAlertID,0L);
  140.         }
  141.     return theResult;
  142. }
  143.  
  144.  
  145. // *****************************************************************************
  146. // *
  147. // *    WriteFile()
  148. // *
  149. // *****************************************************************************
  150. short WriteFile(Document* theDocument)
  151. {    
  152.     short    theResult;
  153.     long    length;
  154.     char*    bufPtr;
  155.  
  156.     SetCursor(*GetCursor(watchCursor));
  157.  
  158.     if (!theDocument->fRefNum)
  159.         return fnOpnErr;
  160.  
  161.     if (theResult = SetFPos(theDocument->fRefNum,fsFromStart,0))
  162.         return theResult;
  163.  
  164.     if (theDocument->theTE != NULL)
  165.         {
  166.         length = (**(theDocument->theTE)).teLength;
  167.         bufPtr = *((**(theDocument->theTE)).hText);
  168.  
  169.         theResult = FSWrite(theDocument->fRefNum,&length,bufPtr);
  170.         if (theResult == noErr)
  171.             theResult = SetEOF(theDocument->fRefNum,length);
  172.         }
  173.     else
  174.         {
  175.         long headerSize = kPictHeaderSize;
  176.         long pictSize = theDocument->fPictLength;
  177.  
  178.         theResult = FSWrite(theDocument->fRefNum,&headerSize,*theDocument->fHeader);
  179.         if (theResult == noErr)
  180.             {
  181.             theResult = FSWrite(theDocument->fRefNum,&pictSize,*theDocument->fPict);    
  182.             if (theResult == noErr)
  183.                 theResult = SetEOF(theDocument->fRefNum,headerSize+pictSize);
  184.             }
  185.         }
  186.  
  187.     return theResult;
  188. }
  189.  
  190.  
  191. // *****************************************************************************
  192. // *
  193. // *    WriteNewFile()
  194. // *
  195. // *****************************************************************************
  196. short WriteNewFile(Document* theDocument, FSSpec* newFileSpec)
  197. {    
  198.     short    theResult;
  199.     short    refNum = 0;
  200.  
  201.     SetCursor(*GetCursor(watchCursor));
  202.  
  203.     theResult = FSpOpenDF(newFileSpec,fsRdWrPerm,&refNum);
  204.     if (refNum != -1)
  205.         {
  206.         if (theResult = SetFPos(refNum,fsFromStart,0))
  207.             return(theResult);
  208.  
  209.         if (theDocument->theTE != NULL)
  210.             {
  211.             long    length;
  212.             char*    bufPtr;
  213.             length = (**(theDocument->theTE)).teLength;
  214.             bufPtr = *((**(theDocument->theTE)).hText);
  215.  
  216.             if (theResult = FSWrite(refNum,&length,bufPtr))
  217.                 return(theResult);
  218.  
  219.             theResult = SetEOF(refNum,length);
  220.             }
  221.         else
  222.             {
  223.             long headerSize = kPictHeaderSize;
  224.             long pictSize = theDocument->fPictLength;
  225.  
  226.             theResult = FSWrite(refNum,&headerSize,*theDocument->fHeader);
  227.             theResult = FSWrite(refNum,&pictSize,*theDocument->fPict);
  228.             
  229.             theResult = SetEOF(refNum,headerSize+pictSize);
  230.             }
  231.         theResult = FSClose(refNum);
  232.         }
  233.     return theResult;
  234. }
  235.  
  236.  
  237. // *****************************************************************************
  238. // *
  239. // *    DoNewDocument()
  240. // *
  241. // *****************************************************************************
  242. void DoNewDocument(Boolean newDocAsPICT)
  243. {    
  244.     Document* theDocument;
  245.     if (theDocument = NewDocument(newDocAsPICT))
  246.         ShowWindow(theDocument->theWindow);
  247. }
  248.  
  249.  
  250. // *****************************************************************************
  251. // *
  252. // *    DoOpenFile()
  253. // *
  254. // *****************************************************************************
  255. OSErr DoOpenFile(FSSpec* theFile, Boolean openAsPICT)
  256. {    
  257.     OSErr        result;
  258.     short        refNum;
  259.     Document*    theDocument = NULL;
  260.  
  261.     result = FSpOpenDF(theFile,fsRdWrPerm,&refNum);
  262.     if ((result == fLckdErr) || (result == afpAccessDenied))
  263.         result = FSpOpenDF(theFile,fsRdPerm,&refNum);
  264.  
  265.     if (result == noErr)
  266.         {
  267.         theDocument = NewDocument(openAsPICT);
  268.         if (theDocument != NULL)
  269.             {
  270.             theDocument->fRefNum = refNum;
  271.             
  272.             result = ReadFile(theDocument);
  273.             if (result == noErr)
  274.                 {
  275.                 SetWTitle(theDocument->theWindow,theFile->name);
  276.                 SizeDocWindow(theDocument);
  277.  
  278.                 AdjustScrollBar(theDocument);
  279.                 ShowWindow(theDocument->theWindow);
  280.                 }
  281.             }
  282.         else
  283.             {
  284.             FSClose(refNum);
  285.             result = memFullErr;
  286.             }
  287.         }
  288.  
  289.     if (result != noErr)
  290.         {
  291.         Str255 errorStr;
  292.         if (result == vLckdErr || result == afpVolLocked || result == wPrErr || result == permErr)
  293.             GetIndString(errorStr,rAppStringsID,sWriteToBusyFileErr);
  294.         else
  295.             if (result == opWrErr)
  296.                 GetIndString(errorStr,rAppStringsID,sBusyOpen);
  297.             else
  298.                 if (result == memFullErr)
  299.                     GetIndString(errorStr,rAppStringsID,sLowMemoryErr);
  300.                 else
  301.                     GetIndString(errorStr,rAppStringsID,sOpeningErr);
  302.         ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  303.         NoteAlert(rGenericAlertID,0L);
  304.         }
  305.  
  306.     return result;
  307. }
  308.  
  309.  
  310. // *****************************************************************************
  311. // *
  312. // *    myFilterProc()
  313. // *
  314. // *****************************************************************************
  315. pascal Boolean myFilterProc(AEDesc* theItem, void* info, NavCallBackUserData /*callBackUD*/, NavFilterModes /*filterMode*/)
  316. {
  317.     OSErr theErr = noErr;
  318.     Boolean display = true;
  319.     NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info;
  320.     
  321.     if ( theItem->descriptorType == typeFSS )
  322.         if ( !theInfo->isFolder )
  323.             {
  324.             // use:
  325.             // 'theInfo->fileAndFolder.fileInfo.finderInfo.fdType'
  326.             // to check for the file type you want to filter.
  327.             }
  328.     return display;
  329. }
  330.  
  331.  
  332. // *****************************************************************************
  333. // *
  334. // *    myEventProc()    
  335. // *
  336. // *****************************************************************************
  337. pascal void myEventProc(const NavEventCallbackMessage callBackSelector, 
  338.                         NavCBRecPtr callBackParms, 
  339.                         NavCallBackUserData callBackUD)
  340. {
  341.     WindowPtr    pWindow = NULL;
  342.     Document**    docList;
  343.     Document*    theDoc = NULL;
  344.     short         index = 0;
  345.  
  346.     if (callBackUD != 0)
  347.         switch (callBackSelector)
  348.             {
  349.             case kNavCBEvent:
  350.                 {
  351.                 docList = (Document**)callBackUD;
  352.                 if (docList != NULL)
  353.                     switch (callBackParms->eventData.event->what)
  354.                         {
  355.                         case nullEvent:
  356.                             break;
  357.                             
  358.                         case updateEvt:
  359.                             pWindow = (WindowPtr)callBackParms->eventData.event->message;
  360.                             theDoc = docList[index];
  361.                             if (theDoc != NULL)
  362.                                 {
  363.                                 while ((theDoc->theWindow != pWindow) && (docList[index] != NULL))
  364.                                     {
  365.                                     index++;
  366.                                     theDoc = docList[index];
  367.                                     }
  368.                                 theDoc = docList[index];
  369.                                 if (theDoc != NULL)
  370.                                     UpdateWindow(theDoc);
  371.                                 }
  372.                             break;
  373.  
  374.                         case activateEvt:
  375.                             break;
  376.  
  377.                         default:
  378.                             break;
  379.                         }
  380.                 break;
  381.                 }
  382.             }
  383. }
  384.  
  385.  
  386. // *****************************************************************************
  387. // *
  388. // *    DoOpenDocumentTheOldWay()
  389. // *
  390. // *****************************************************************************
  391. OSErr DoOpenDocumentTheOldWay()
  392. {    
  393.     OSErr theErr = noErr;
  394.     SFTypeList            theTypeList;
  395.     StandardFileReply    theReply;
  396.  
  397.     theTypeList[0] = 'TEXT';
  398.     theTypeList[1] = 'PICT';
  399.     StandardGetFile(0L,2,theTypeList,&theReply);
  400.  
  401.     if (theReply.sfGood)
  402.         {
  403.         if (theReply.sfType == 'TEXT')
  404.             DoOpenFile(&theReply.sfFile,false);
  405.         else
  406.             DoOpenFile(&theReply.sfFile,true);
  407.         }
  408.     return theErr;
  409. }
  410.  
  411.  
  412.  
  413.  
  414. // *****************************************************************************
  415. // *
  416. // *    DoOpenDocument()
  417. // *
  418. // *****************************************************************************
  419. OSErr DoOpenDocument()
  420. {    
  421.     NavReplyRecord        theReply;
  422.     NavDialogOptions    dialogOptions;
  423.     OSErr                theErr = noErr;
  424.     NavTypeListHandle    openList = NULL;
  425.     long                count = 0;
  426.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  427.     NavObjectFilterUPP    filterUPP = NewNavObjectFilterProc(myFilterProc);
  428.     
  429.     // default behavior for browser and dialog:
  430.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  431.  
  432.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  433.     
  434.     openList = (NavTypeListHandle)GetResource(kOpenRsrcType,kOpenRsrcID);
  435.  
  436.     dialogOptions.preferenceKey = kOpenPrefKey;
  437.  
  438.     dialogOptions.dialogOptionFlags += kNavDontAutoTranslate;    // we will do the translation ourselves later:
  439.  
  440.     theErr = NavGetFile(NULL,    // use system's default location
  441.                         &theReply,
  442.                         &dialogOptions,
  443.                         eventUPP,
  444.                         NULL,    // no custom previews
  445.                         filterUPP,
  446.                         (NavTypeListHandle)openList,
  447.                         (NavCallBackUserData)&gDocumentList);
  448.  
  449.     DisposeRoutineDescriptor(eventUPP);
  450.     DisposeRoutineDescriptor(filterUPP);
  451.  
  452.     if (theReply.validRecord && theErr == noErr)
  453.         {
  454.         // since we allow for multiple objects to be returned,
  455.         // grab the target FSSpecs from 'theReply.fileRef' list for opening:    
  456.         FSSpec    finalFSSpec;    
  457.         AEDesc     resultDesc;
  458.         FInfo    fileInfo;
  459.  
  460.         // in the case we didn't want built in translation:
  461.         if ((dialogOptions.dialogOptionFlags & kNavDontAutoTranslate) != 0)
  462.             if (theReply.translationNeeded)
  463.                 {
  464.                 // if we didn't want built in translation it was for the following reasons:
  465.                 //        1) we wanted to do it ourselves
  466.                 //        2) or we wanted to defer it    
  467.                 // things to remember if auto-translation is turned off:
  468.                 //         1) the AEDesc list contains the original file specs the user had chosen.
  469.                 //        2) the 'fileTranslation' field for each object that needs translation has filled in for you.
  470.                 
  471.                 // put your own code here to perform your own translation.
  472.                 // - or -
  473.                 // we can simply call this to perform the translation manually:
  474.                 Str255     errorStr;
  475.  
  476.                 if ((theErr = NavTranslateFile(&theReply,kNavTranslateCopy)) != noErr)
  477.                     {
  478.                     if (theErr == vLckdErr || theErr == afpVolLocked || theErr == wPrErr || theErr == permErr)
  479.                         GetIndString(errorStr,rAppStringsID,sTranslationLockedErr);
  480.                     else
  481.                         GetIndString(errorStr,rAppStringsID,sTranslationErr);
  482.                     ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  483.                     NoteAlert(rGenericAlertID,0L);
  484.                     }
  485.                 }
  486.  
  487.         if (theErr == noErr)
  488.             {
  489.             // we are ready to open the document(s), grab information about each file for opening:
  490.             theErr = AECountItems(&(theReply.selection),&count);
  491.             for (long index=1;index<=count;index++)
  492.                 {
  493.                 resultDesc.dataHandle = 0L;
  494.                 if ((theErr = AEGetNthDesc(&(theReply.selection),index,typeFSS,NULL,&resultDesc)) == noErr)
  495.                     {
  496.                     BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  497.                 
  498.                     // decide if the doc we are opening is a 'PICT' or 'TEXT':
  499.                     if ((theErr = FSpGetFInfo(&finalFSSpec,&fileInfo)) == noErr)
  500.                         {
  501.                         if (fileInfo.fdType == kFileType)
  502.                             (void)DoOpenFile(&finalFSSpec,false);
  503.                         else
  504.                             if (fileInfo.fdType == kFileTypePICT)
  505.                                 (void)DoOpenFile(&finalFSSpec,true);
  506.                             else
  507.                                 {
  508.                                 // error:
  509.                                 // if we got this far, the document is a type we can't open and
  510.                                 // (most likely) built-in translation was turned off.
  511.                                 // You can alert the user that this returned selection or file spec
  512.                                 // needs translation.
  513.                                 }
  514.                         }
  515.                     theErr = AEDisposeDesc(&resultDesc);
  516.                     }
  517.                 }
  518.             }
  519.         
  520.         theErr = NavDisposeReply(&theReply);    // clean up after ourselves    
  521.         }
  522.  
  523.     if (openList != NULL)
  524.         ReleaseResource((Handle)openList);
  525.  
  526.     return theErr;
  527. }
  528.  
  529.  
  530. // *****************************************************************************
  531. // *
  532. // *    SaveACopyDocumentTheOldWay()
  533. // *
  534. // *****************************************************************************
  535. OSErr SaveACopyDocumentTheOldWay(Document* theDocument)
  536. {
  537.     OSErr                theErr = noErr;
  538.     Str255                thePrompt, theName;
  539.     StandardFileReply    theReply;
  540.  
  541.     if (!theDocument)
  542.         return false;
  543.  
  544.     GetIndString((unsigned char*)&thePrompt,rAppStringsID,sSaveCopyMessage);
  545.     GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  546.     StandardPutFile((unsigned char*)&thePrompt,(unsigned char*)&theName,&theReply);
  547.  
  548.     if (theReply.sfGood)
  549.         {
  550.         if (theReply.sfReplacing)
  551.             theErr = FSpDelete(&theReply.sfFile);
  552.  
  553.         if ((theErr = FSpCreate(&theReply.sfFile,kFileCreator,'TEXT',smSystemScript)) == noErr)
  554.             theErr = WriteNewFile(theDocument,&theReply.sfFile);    // use this document's data to write to our new copy:
  555.         
  556.         if (theErr == fBsyErr)
  557.             {
  558.             Str255 errorStr;
  559.             GetIndString(errorStr,rAppStringsID,sWriteToBusyFileErr);
  560.             ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  561.             NoteAlert(rGenericAlertID,0L);
  562.             }
  563.         }
  564.     else
  565.         return false;
  566.         
  567.     return true;
  568. }
  569.  
  570.  
  571. // *****************************************************************************
  572. // *
  573. // *    SaveACopyDocument()
  574. // *
  575. // *****************************************************************************
  576. OSErr SaveACopyDocument(Document* theDocument)
  577. {    
  578.     OSErr                theErr = noErr;
  579.     NavReplyRecord        theReply;
  580.     NavDialogOptions    dialogOptions;
  581.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  582.     Str255                docTitle;
  583.     OSType                fileTypeToSave;
  584.  
  585.     // default behavior for browser and dialog:
  586.     theErr = NavGetDefaultDialogOptions(&dialogOptions);
  587.  
  588.     // user might want to translate the saveed doc into another format
  589.     dialogOptions.dialogOptionFlags -= kNavDontAddTranslateItems;
  590.  
  591.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  592.  
  593.     GetWTitle(theDocument->theWindow,docTitle);
  594.     p2cstr((StringPtr)docTitle);
  595.     sprintf((char*)dialogOptions.savedFileName,(char*)"%s copy",docTitle);
  596.     c2pstr((Ptr)dialogOptions.savedFileName);
  597.         
  598.     if (theDocument->theTE != NULL)    // which document type is it?
  599.         fileTypeToSave = kFileType;
  600.     else
  601.         fileTypeToSave = kFileTypePICT;
  602.  
  603.     dialogOptions.preferenceKey = kSavePrefKey;
  604.  
  605.     theErr = NavPutFile(NULL,    // use system's default location
  606.                         &theReply,
  607.                         &dialogOptions,
  608.                         eventUPP,
  609.                         fileTypeToSave,
  610.                         kFileCreator,
  611.                         (NavCallBackUserData)&gDocumentList);
  612.  
  613.     DisposeRoutineDescriptor(eventUPP);
  614.  
  615.     if (theReply.validRecord && theErr == noErr)
  616.         {
  617.         FSSpec    finalFSSpec;    
  618.         AEDesc     resultDesc;    
  619.         resultDesc.dataHandle = 0L;
  620.         
  621.         // retrieve the returned selection:
  622.         // since only 1 selection is possible, we get the first AEDesc:
  623.         if ((theErr = AEGetNthDesc(&(theReply.selection),1,typeFSS,NULL,&resultDesc)) == noErr)
  624.             {
  625.             BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  626.  
  627.             if (theReply.replacing)
  628.                 theErr = FSpDelete(&finalFSSpec);
  629.             if (theErr == noErr)
  630.                 {
  631.                 if ((theErr = FSpCreate(&finalFSSpec,kFileCreator,fileTypeToSave,smSystemScript)) == noErr)
  632.                     if ((theErr = WriteNewFile(theDocument,&finalFSSpec)) == noErr)    // use this document's data to write to our new copy
  633.                         {
  634.                         // translation may be needed for file we are saving a copy of,
  635.                         // when you save a copy, you should always "translate in place":
  636.                         theErr = NavCompleteSave(&theReply,kNavTranslateInPlace);
  637.                         }
  638.                 }
  639.             else
  640.                 if (theErr == fBsyErr)
  641.                     {
  642.                     Str255 errorStr;
  643.                     GetIndString(errorStr,rAppStringsID,sReadErr);
  644.                     ParamText((ConstStr255Param)&errorStr,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  645.                     NoteAlert(rGenericAlertID,0L);
  646.                     }
  647.  
  648.             AEDisposeDesc(&resultDesc);
  649.             }
  650.         theErr = NavDisposeReply(&theReply);
  651.         }
  652.     
  653.     return theErr;
  654. }
  655.  
  656.  
  657. // *****************************************************************************
  658. // *
  659. // *    DoSaveAsDocument()
  660. // *
  661. // *****************************************************************************
  662. short DoSaveAsDocument(Document* theDocument)
  663. {
  664.     OSErr                theErr = noErr;
  665.     short                result = true;
  666.     NavReplyRecord        theReply;
  667.     NavDialogOptions    dialogOptions;
  668.     NavEventUPP            eventUPP = NewNavEventProc(myEventProc);
  669.     OSType                fileTypeToSave;
  670.  
  671.     // default behavior for browser and dialog:
  672.     NavGetDefaultDialogOptions(&dialogOptions);
  673.  
  674.     // user might want to translate the saveed doc into another format
  675.     dialogOptions.dialogOptionFlags -= kNavDontAddTranslateItems;
  676.  
  677.     GetWTitle(theDocument->theWindow,dialogOptions.savedFileName);
  678.     GetIndString((unsigned char*)&dialogOptions.clientName,rAppStringsID,sApplicationName);
  679.             
  680.     if (theDocument->theTE != NULL)    // which document type is it?
  681.         fileTypeToSave = kFileType;
  682.     else
  683.         fileTypeToSave = kFileTypePICT;
  684.  
  685.     dialogOptions.preferenceKey = kSavePrefKey;
  686.  
  687.     theErr = NavPutFile(NULL,    // use system's default location
  688.                         &theReply,
  689.                         &dialogOptions,
  690.                         eventUPP,
  691.                         fileTypeToSave,
  692.                         kFileCreator,
  693.                         (NavCallBackUserData)&gDocumentList);
  694.     DisposeRoutineDescriptor(eventUPP);
  695.  
  696.     if (theReply.validRecord && theErr == noErr)
  697.         {
  698.         FSSpec    finalFSSpec;    
  699.         AEDesc     resultDesc;    
  700.         resultDesc.dataHandle = 0L;
  701.         
  702.         // retrieve the returned selection:
  703.         if ((theErr = AEGetNthDesc(&(theReply.selection),1,typeFSS,NULL,&resultDesc)) == noErr)
  704.             {
  705.             BlockMoveData(*resultDesc.dataHandle,&finalFSSpec,sizeof(FSSpec));
  706.  
  707.             if (!theReply.replacing)
  708.                 {
  709.                 result = FSpCreate(&finalFSSpec,kFileCreator,fileTypeToSave,theReply.keyScript);
  710.                 if (result)
  711.                     {
  712.                     SysBeep(5);
  713.                     return false;
  714.                     }
  715.                 }
  716.                 
  717.             if (theDocument->fRefNum)
  718.                 result = FSClose(theDocument->fRefNum);
  719.             
  720.             result = FSpOpenDF(&finalFSSpec,fsRdWrPerm,&theDocument->fRefNum);
  721.             if (result)
  722.                 {
  723.                 SysBeep(5);
  724.                 return false;
  725.                 }
  726.  
  727.             if (result = WriteFile(theDocument))
  728.                 return false;
  729.  
  730.             AEDisposeDesc(&resultDesc);
  731.  
  732.             theErr = NavCompleteSave(&theReply,kNavTranslateInPlace);
  733.  
  734.             SetWTitle(theDocument->theWindow,(unsigned char*)finalFSSpec.name);
  735.             theDocument->dirty = false;
  736.             }
  737.  
  738.         NavDisposeReply(&theReply);
  739.         }
  740.     else
  741.         return false;
  742.  
  743.     return result;
  744. }
  745.  
  746.  
  747. // *****************************************************************************
  748. // *
  749. // *    DoSaveAsDocumentOldWay()
  750. // *
  751. // *****************************************************************************
  752. short DoSaveAsDocumentOldWay(Document* theDocument)
  753. {    
  754.     short                theResult;
  755.     Str255                thePrompt, theName;
  756.     StandardFileReply    theReply;
  757.     OSType                fileTypeToSave;
  758.  
  759.     if (!theDocument)
  760.         return false;
  761.  
  762.     GetIndString((unsigned char*)&thePrompt,rAppStringsID,slSavePromptIndex);
  763.     GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  764.     StandardPutFile((unsigned char*)&thePrompt,(unsigned char*)&theName,&theReply);
  765.  
  766.     if (theDocument->theTE != NULL)    // which document type is it?
  767.         fileTypeToSave = kFileType;
  768.     else
  769.         fileTypeToSave = kFileTypePICT;
  770.  
  771.     if (theReply.sfGood)
  772.         {
  773.         if (!theReply.sfReplacing)
  774.             {
  775.             theResult = FSpCreate(&theReply.sfFile,kFileCreator,fileTypeToSave,theReply.sfScript);
  776.             if (theResult)
  777.                 {
  778.                 SysBeep(5);
  779.                 return false;
  780.                 }
  781.             }
  782.             
  783.         if (theDocument->fRefNum)
  784.             theResult = FSClose(theDocument->fRefNum);
  785.         
  786.         theResult = FSpOpenDF(&theReply.sfFile,fsRdWrPerm,&theDocument->fRefNum);
  787.         if (theResult)
  788.             {
  789.             SysBeep(5);
  790.             return false;
  791.             }
  792.  
  793.         if (theResult = WriteFile(theDocument))
  794.             {
  795.             SysBeep(5);
  796.             return false;
  797.             }
  798.  
  799.         SetWTitle(theDocument->theWindow,(unsigned char*)theReply.sfFile.name);
  800.         theDocument->dirty = false;
  801.         }
  802.     else
  803.         return false;
  804.         
  805.     return true;
  806. }
  807.  
  808.  
  809. // *****************************************************************************
  810. // *
  811. // *    DoSaveDocument()
  812. // *
  813. // *****************************************************************************
  814. short DoSaveDocument(Document* theDocument)
  815. {
  816.     short theErr = noErr;
  817.     if (theDocument != NULL)
  818.         {
  819.         if (theDocument->fRefNum)
  820.             {
  821.             if (WriteFile(theDocument))
  822.                 {
  823.                 SysBeep(5);
  824.                 return false;
  825.                 }
  826.             else
  827.                 theDocument->dirty = false;
  828.             theErr = true;
  829.             }
  830.         else
  831.             {
  832.             // need to save file for the first time:
  833.             if (gNavServicesExists)
  834.                 theErr = DoSaveAsDocument(theDocument);
  835.             else
  836.                 theErr = DoSaveAsDocumentOldWay(theDocument);
  837.  
  838.             if (theErr == memFullErr)
  839.                 theErr = DoSaveAsDocumentOldWay(theDocument);
  840.             }
  841.         }
  842.     return theErr;
  843. }
  844.  
  845.  
  846. // *****************************************************************************
  847. // *
  848. // *    DoRevertDocument()
  849. // *
  850. // *****************************************************************************
  851. void DoRevertDocument(Document* theDocument)
  852. {    
  853.     if (theDocument != NULL)
  854.     if (theDocument->fRefNum)
  855.         {
  856.         OSErr                         theErr = noErr;
  857.         NavEventUPP                    eventUPP = NewNavEventProc(myEventProc);
  858.         NavAskDiscardChangesResult     reply;
  859.         NavDialogOptions            dialogOptions;
  860.  
  861.         GetWTitle(theDocument->theWindow,dialogOptions.savedFileName);
  862.         theErr = NavAskDiscardChanges(    &dialogOptions,
  863.                                         &reply,
  864.                                         eventUPP,
  865.                                         (NavCallBackUserData)&gDocumentList);
  866.         DisposeRoutineDescriptor(eventUPP);
  867.  
  868.         switch (reply)
  869.             {
  870.             case kNavAskDiscardChanges:        
  871.                 if (ReadFile(theDocument))
  872.                     SysBeep(5);
  873.                 break;
  874.  
  875.             case kNavAskDiscardChangesCancel:
  876.                 break;
  877.             }
  878.         }
  879. }
  880.  
  881.  
  882. // *****************************************************************************
  883. // *
  884. // *    DoRevertDocumentTheOldWay()
  885. // *
  886. // *****************************************************************************
  887. void DoRevertDocumentTheOldWay(Document* theDocument)
  888. {    
  889.     Str255 theName;
  890.  
  891.     if (!theDocument)
  892.         return;
  893.  
  894.     if (theDocument->fRefNum)
  895.         {
  896.         GetWTitle(theDocument->theWindow,(unsigned char*)&theName);
  897.         ParamText((ConstStr255Param)&theName,(ConstStr255Param)"\p",(ConstStr255Param)"\p",(ConstStr255Param)"\p");
  898.         if (Alert(rRevertID,0L) == 1)
  899.             if (ReadFile(theDocument))
  900.                 SysBeep(5);
  901.         }
  902. }
  903.